The Developer Fastlane

« 365 days to become a developer » challenge

PHP OOP: Object inheritance

November 20, 2020

Lesson

1. Parent & child classes

extends

The extend keyword allows a child class to inherit from another class' methods and properties (the parent class).
Here is the syntax to use it:
Code
        class ChildClass extends PerentClass {
            // Do some stuff in here...
            // We can use the parent::abc(); attribute to get the result of the parent abc() method and change it.
        }
This technique saves a lot of code: no need to copy-paste or repeat it in the child class.
Below is the detaile code for:
  • Parent class: gathers a couple of methods that track page views on a website (increments a counter in a external text file each time a page is visited and then display the counter inside the footer.
  • Child class: a broken counter that display the double numbers of visites (this is a dumb example just to make easier to understand the parent/child logic).
DoubleCounter.php (child)
Code
<?php
require_once __DIR__ . DIRECTORY_SEPARATOR . 'Counter.php'; // 1. Call the parent class file

class CounterDouble extends Counter { // 2. tell this is an extension of the parent class

    public function get_views(): int
    {
        return 2 * parent::get_views(); // 3. Just change the output as needed
    }

}
Counter.php (parent)
Code
<?php

class Counter {

    public $file;

    public function __construct(string $var1)
    {
        $this->file = $var1;
    }
    public function increment(): void
    {
        if (file_exists($this->file)) {
            $views = (int)file_get_contents($this->file);
            $views++;
        } else {
            $views = 1;
        }
        file_put_contents($this->file, $views);
    }
    public function get_views(): int
    {
        if (!file_exists($this->file)) {
            return 0;
        }
        return (int)file_get_contents($this->file);
    }

}
footer.php
Code
<div class="col-md-4">
    <h5>Counter Double</h5>
    <ul class="list-unstyled">
        <li>
            <?php 
                require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'class' . DIRECTORY_SEPARATOR . 'CounterDouble.php'; 
                $counter = new CounterDouble(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'page-views');
                $counter->increment();
                $pageViews = $counter->get_views();
                echo "<b>$pageViews</b> page view";
                if ($pageViews > 1) { echo "s"; }
            ?>
        </li>
    </ul>
</div>
... Instead of doing this (reapeating the code and just change the class name and file):
Code
// CounterDouble.php

    <?php

    class CounterDouble {

        public $file;

        public function __construct(string $var1)
        {
            $this->file = $var1;
        }
        public function increment(): void
        {
            if (file_exists($this->file)) {
                $views = (int)file_get_contents($this->file);
                $views++;
            } else {
                $views = 1;
            }
            file_put_contents($this->file, $views);
        }
        public function get_views(): int
        {
            if (!file_exists($this->file)) {
                return 0;
            }
            return 2 * (int)file_get_contents($this->file); 
                // This is the only modification of the code...
        }

    }

2. Methods / variables visibility

The are 3 types of visibility parameters we can apply to both methods and properties in a class:
  • public: It can be accessed from the inside as well as from the outside.
  • private: It can only be accessed from the inside in the same class.
  • protected: It can only be accessed from the inside in the same class or in the children's classes.

Why don't we always use "public"?

  • This is primarily for a question of code organization: using the "private" or "protected" parameters allows us to know where the property or method can be used or not.
  • As an example, working with a class built by someone else (in a wordpress plugin or in a framework like Symfony for example), if we see a "protected" property inside a class, then we know directly that we won't need to use this property while working with this class.
  • Only the __construct method is alway public.

Final remarks

  • These rules will work as well for instance methods as for static methods. We can write as well:
    • private static function abc()
    • protected static function abc()

3. Constants

  • Constants are like properties, to the difference that they never change.
  • They are written in full uppercase letters as for functions' constants. Example: CONSTANT.
  • It's considered as a static property, so we need to use self:: to use it inside a class method. example: self::CONSTANT
  • We use the static:: attribute in the parent class to allow the constant to be shared in childrens ones (have a look to the code below!)

Counter10x.php (parent)
Code
<?php
require_once __DIR__ . DIRECTORY_SEPARATOR . 'Counter.php';

class Counter10x extends Counter {

    const INCREMENT = 10;

}
Counter.php (child)
Code
<?php

class Counter {

    const INCREMENT = 1;
    public $file;

    public function __construct(string $var1)
    {
        $this->file = $var1;
    }
    public function increment(): void
    {
        if (file_exists($this->file)) {
            $views = (int)file_get_contents($this->file);
            $views += static::INCREMENT; 
                // Note: we use the static:: attribute here instead of self:: as for regular properties
                // (using self:: the property would refer to the parent and not child constante)!
        } else {
            $views = 1;
        }
        file_put_contents($this->file, $views);
    }
    public function get_views(): int
    {
        if (!file_exists($this->file)) {
            return 0;
        }
        return (int)file_get_contents($this->file);
    }

}
© 2020 - Edouard Proust | The Developer Fastlane